home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.std.c++
- Path: cs.mu.OZ.AU!bounce-back
- From: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
- Subject: Re: Give operator. a chance
- Message-ID: <9601281318.9776@mulga.cs.mu.OZ.AU>
- Originator: fjh@munta.cs.mu.OZ.AU
- Sender: news@cs.mu.OZ.AU (CS-Usenet)
- Organization: Computer Science, University of Melbourne, Australia
- References: <3102AD11.1663@et.se> <4e8g4t$aa3@hermes.synopsys.com> <4easfd$puc@news2.delphi.com>
- X-Original-Date: Mon, 29 Jan 1996 00: 18:14 +1100
- Date: Sun, 28 Jan 1996 23:58:45 GMT
- Approved: fjh@cs.mu.oz.au
- X-Auth: PGPMoose V1.1 PGP comp.std.c++
- iQBFAgUBMQwObuEDnX0m9pzZAQFk9QF8Cf/vu/js/KtVsANEP/lg2g/40bF8hNwO
- B/mrmEb51NBiYn9HHZVwGbj3Cvy1ugk6
- =5ilC
-
- jodle@bix.com (jodle) writes:
-
- >I'm afraid there is something I don't understand about this approach. For
- >a nontrivial class, one in which you have a delegate pointer and other
- >members, how would you propose the compiler discriminate between
- >overloaded (delegative) member selection and the selection of actual
- >members of the class? This would become an issue as soon as a member
- >function tries to access member data or a user of the class attempts to
- >form a call to a member function.
-
- Jim Adcock proposed that if `.' was overloaded, then `.' always meant
- the overloaded version, not the built-in version. That's what I
- implemented. I think these simple semantics are quite sufficient to
- achieve the desired functionality. Here's the documentation included
- in the gcc patch I previously posted, which explains how the problem
- you refer to can be solved.
-
- -----------------------------------------------------------------------------
-
- Overloading Operator Dot for Smart References
- =============================================
-
- Just as standard C++ allows you to overload `operator->()' to create
- "Smart Pointer" classes, GNU C++ allows you to overload `operator.()'
- to create "Smart Reference" classes.
-
- Overloading `operator->()' or `operator.()' is different to
- overloading the other binary operators, because the right hand operand
- is a field name, not an expression. The overloaded operator function
- takes only a single argument, the left hand operand, and returns a
- pointer (for `operator->()') or a reference (for `operator.()') which
- the compiler then uses in combination with the field name to produce
- the final result. Essentially, overloading operator dot is exactly the
- same as overloading operator arrow except that where operator arrow
- uses pointers, operator dot uses references.
-
- For any class X which overloads the dot operator, the compiler
- replaces all expressions of the form `x.m' with `(x.operator.()).m'.
- If the result of `X::operator.()' is a class type which also overloads
- dot, then the result is recursively subject to the same expansion.
- (Note that the first dot in `x.operator.()' is meant to represent the
- builtin operator dot and is not subject to recursive expansion, for
- otherwise we would get an infinite regress.)
-
- The overloaded `operator.()' will be invoked only when there is an
- actual dot operator present in the source code. If a member function is
- invoked without using a dot operator, then `operator.()' will *not* be
- invoked. Conversely, a dot expression *always* invokes the appropriate
- `operator.()' if that operator has been overloaded. This means that if
- class `X' contains a member function `f()' but `X' overloads operator
- dot to return `Y&', then the following code
-
- X x;
- x.f();
-
- calls `Y::f()', not `X::f()'.
-
- Most of the time, this behaviour is exactly what you want.
- Sometimes however, you do want to access member functions of your smart
- reference class. For example, suppose you have defined a class
- `DiskReference' which acts as a reference to data which is stored on
- disk. The class caches the disk value in memory, and the cache is
- written back to the disk by the destructor. Your class users may
- occaisionally want to explicitly flush the cache, so the `DiskReference'
- class should provide a class method `flush()' to do that.
-
- If you do want to access members of `DiskReference', then you need
- to do so without using the dot operator. If the member(s) you want to
- access are overloaded operators, then you can just use the operator
- notation. For other members, if you haven't overloaded `operator&()',
- you can use `(&x)->m'. But it's often nice to overload operator& to
- return a smart pointer. In this case, the best thing to do is to put
- most of the details of DiskReference in a base class, say
- DiskReferenceControl, which doesn't overload operator dot, and then
- invoke the members using a reference to DiskReferenceControl. For
- example:
-
- foo(DiskReference& x) {
- DiskReferenceControl& x_control(x);
- x_control.flush(); // flushes x to disk
- }
-
- You could also simplify the calling of DiskReferenceControl member
- functions, using a helper function a function `control()' like this:
-
- inline DiskReferenceControl& control(DiskReference& x) { return x; }
-
- foo(DiskReference& x) {
- control(x).flush();
- }
-
- -----------------------------------------------------------------------------
-
- Another alternative not mentioned in the documentation is do just
- put all the relevant functions in the smart pointer, not the
- smart reference; if you need to invoke one of them on a smart
- reference, use the overloaded & operator to convert from a smart
- reference to a smart pointer: `(&x).foo();'.
-
- >The -> operator has the advantage that it signals the delegation property
- >of the member selection when it's performed. It's easy enough for the
- >programmer to ignore that aspect when it's adventageous for him to do so.
- >It is also easy enough to identify that aspect when it is an issue. "I
- >know this identifier is a reference or an object but here is this pointer
- >member selection operator being used so I know delegation is being used."
-
- Overloadable operator -> is great, but it only gives you smart pointers,
- not smart references. I think the approach outlined above has similar
- advantages of making it clear when delegated members are being selected
- and when the non-delegated members are being selected. But the point of
- overloading . rather than -> it gives you smart references, not smart pointers.
-
-
- --
- Fergus Henderson WWW: http://www.cs.mu.oz.au/~fjh
- fjh@cs.mu.oz.au PGP: finger fjh@128.250.37.3
- ---
- [ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
- Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
- is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
-